"""
井字棋

逻辑如下：
背景为棋盘150*200
3*3，每个格子大小为50
另在最上面提供一个展示信息的bar

棋子分两种：
o和x各自表示
o表示为一个半径为40的圆
x表示为两条直线相交，高宽也各为40

o子先下，x子后下，各自轮换
可以下的位置是任何空位置。

共计9个位置，使用二维数组记录。
0表示空；
1表示p1落子；2表示p2落子。

结束条件：
1. 【优先判定】某一方获得胜利，即横向、纵向、斜向的任一条线，均是1或2；
2. 9个位置已被下满。

不需要考虑：
1. AI要素。使用人轮流操作。


"""
from __future__ import annotations

import math

import arcade


SCREEN_WIDTH=150
SCREEN_HEIGHT=200
SCREEN_TTTLE='tic tac toe'


class TicTocToe:

    def __init__(self):
        # 初始化二维数组
        # 约定：0未落子，1为0落子，2为x落子
        self.reset_info()

        # 初始化展示信息
        self.draw_board()

        pass
    
    def reset_info(self):
        # 重置信息
        self.board=[[0]*3 for _ in range(3)]
        self.next='o'
        self.end_mark=0
        self.show_info=''


    def refresh_end_mark(self)->None:
        # 刷新结束标记
        # 约定：0未结束；1结束且o胜利，2结束且x胜利，3结束且平局
        if self.end_mark!=0:
            return
        
        # o胜利判定
        if ((self.board[0][0]==self.board[0][1]==self.board[0][2]==1) 
            or (self.board[1][0]==self.board[1][1]==self.board[1][2]==1)
            or (self.board[2][0]==self.board[2][1]==self.board[2][2]==1)
            or (self.board[0][0]==self.board[1][0]==self.board[2][0]==1)
            or (self.board[0][1]==self.board[1][1]==self.board[2][1]==1)
            or (self.board[0][2]==self.board[1][2]==self.board[2][1]==1)
            or (self.board[0][0]==self.board[1][1]==self.board[2][2]==1)
            or (self.board[0][2]==self.board[1][1]==self.board[2][0]==1)
            ):
            self.end_mark=1
            return
        
        # x胜利判定
        if ((self.board[0][0]==self.board[0][1]==self.board[0][2]==2) 
            or (self.board[1][0]==self.board[1][1]==self.board[1][2]==2)
            or (self.board[2][0]==self.board[2][1]==self.board[2][2]==2)
            or (self.board[0][0]==self.board[1][0]==self.board[2][0]==2)
            or (self.board[0][1]==self.board[1][1]==self.board[2][1]==2)
            or (self.board[0][2]==self.board[1][2]==self.board[2][1]==2)
            or (self.board[0][0]==self.board[1][1]==self.board[2][2]==2)
            or (self.board[0][2]==self.board[1][1]==self.board[2][0]==2)
            ):
            self.end_mark=2
            return


        # 平局判定
        move_over=True
        for ridx in range(3):
            for cidx in range(3):
                if self.board[ridx][cidx]==0:
                    move_over=False
        if move_over:
            self.end_mark=2
            return

        pass


    def refresh_show_info(self)->None:
        # 刷新展示信息
        if self.end_mark==0:
            if self.next=='o':
                self.show_info='请玩家o落子'
            else:
                self.show_info='请玩家x落子'
        elif self.end_mark==1:
            self.show_info='玩家o胜利'
        elif self.end_mark==2:
            self.show_info='玩家x胜利'

        pass

    def draw_board(self):
        # 画棋盘
        # (0,50)~(150,50)
        # (0,100)~(150,100)
        # (0,150)~(150,150)
        # (50,0)~(50,150)
        # (100,0)~(100,150)
        arcade.draw_line(0,50,150,50,arcade.color.WHITE)
        arcade.draw_line(0,100,150,100,arcade.color.WHITE)
        arcade.draw_line(0,150,150,150,arcade.color.WHITE)
        arcade.draw_line(50,0,50,150,arcade.color.WHITE)
        arcade.draw_line(100,0,100,150,arcade.color.WHITE)

        pass

    def calc_center_xy_by_rc(self,row,col):
        x=col*50+25
        br=2-row
        y=br*50+25
        return (x,y)
    
    def calc_rc_by_xy(self,x,y):
        c=x//50
        br=y//50
        if c>2 or br>2:
            return None
        return (int(2-br),int(c))

    def draw_piece_o(self,row,col):
        # 画棋子o
        x,y=self.calc_center_xy_by_rc(row,col)
        arcade.draw_circle_outline(x,y,20,arcade.color.WHITE)
        pass

    def draw_piece_x(self,row,col):
        # 画棋子x
        x,y=self.calc_center_xy_by_rc(row,col)
        # arcade.draw_circle_outline(x,y,20,arcade.color.GREEN)
        arcade.draw_line(x-20,y-20,x+20,y+20,arcade.color.WHITE)
        arcade.draw_line(x-20,y+20,x+20,y-20,arcade.color.WHITE)

        pass

    def draw_piece_all(self):
        # 画所有落子
        for ridx in range(3):
            for cidx in range(3):
                if(self.board[ridx][cidx]==1):
                    self.draw_piece_o(ridx,cidx)
                elif(self.board[ridx][cidx]==2):
                    self.draw_piece_x(ridx,cidx)


    def draw_show_info(self):
        # 画展示信息
        # 中间位置是(75,175)
        arcade.draw_text(self.show_info,0,175,arcade.color.WHITE,align='center')

        pass

    


class BoardWindow(arcade.Window):

    def __init__(self):
        # 初始化棋盘信息
        super().__init__(SCREEN_WIDTH,SCREEN_HEIGHT,SCREEN_TTTLE)
        arcade.set_background_color(arcade.color.BLACK)

        # 画出初始棋盘
        self.ttt=TicTocToe()

        pass

    def on_draw(self):
        self.clear()

        # 画棋盘
        self.ttt.draw_board()

        # 画已经下的棋子
        self.ttt.draw_piece_all()

        # 画当前出手人，或游戏是否结束（是否有人胜利）
        self.ttt.draw_show_info()
        
        pass

    def on_mouse_press(self, x, y, button, modifiers):
        
        # 判断游戏是否结束，如果已结束则不触发
        if(self.ttt.end_mark!=0):
            return

        # 判断点击位置是否在空位置上
        rc=self.ttt.calc_rc_by_xy(x,y)
        
        # 如果在空位置上，则落子且记录
        if rc is None:
            return
        print(rc)
        r,c=rc


        # 落子后判定是否结束
        if self.ttt.next=='o':
            self.ttt.board[r][c]=1
            self.ttt.next='x'
        else:
            self.ttt.board[r][c]=2
            self.ttt.next='o'

        # 如果未结束，则修改展示信息
        self.ttt.refresh_end_mark()
        self.ttt.refresh_show_info()

        # 日志打印
        # for row in self.ttt.board:
        #     print(row)
        

        pass

def main():
    w=BoardWindow()
    arcade.run()

    pass

if __name__=='__main__':
    main()